
#include "MCE.h"

//================================================================================================================================
// The tag table
//================================================================================================================================
struct mtags {
             char *tag;                   // Tag name
             int  tag_length;             // Length of the tag name
             char data_type;              // type of the associated value String, MINT or Boolean
//             char *description;         // Text description of this tag
             int  istate;                 // Associated MINT value received for this tag
             char cstate[MAX_CSTATE+1];   // Associated string value received for this tag
             union
               { char tstate[9];              // Associated time string value received for this tag
                 double td;
               };
             char display[MAX_CSTATE+1];  // what to display for this tag
             } mtags [NUM_MTAGS+1] =
             {
      		   {"Status",                               6,MSTR,0,"Undefined",	"00:00:00","Status"	     },	/* Media Centre Status */
               {"Application",                         11,MUNK,0,"Undefined",	"00:00:00","Application" },	/* Not used by components. */
               {"ArtistName",                          10,MSTR,0,"Undefined",	"00:00:00","Unknown"	 },	/* Name of the artist associated with the current track. This status is sent when the track starts. */
               {"CallingPartyName",                    16,MSTR,0,"Undefined",	"00:00:00","CallingPartyName"},	/* Name of the caller making the incoming phone call. */
               {"CallingPartyNumber",                  18,MINT,0,"Undefined",	"00:00:00","CallingPartyNumber"}, /* Phone number of the caller making the incoming phone call. */
               {"CD",                                   2,MBOO,0,"False",		"00:00:00","CD"	         },	/* CD playback has started. */
               {"CurrentPicture",                      14,MSTR,0,"Undefined",	"00:00:00","CurrentPicture"}, /* Name of the current picture. This status is sent when a new picture is selected. */
               {"DialogVisible",                       13,MBOO,0,"False",		"00:00:00","DialogVisible"}, /* True if there is a dialogue box open */
               {"DiscWriter_ProgressTimeChanged",      30,MTIM,0,"Undefined",	"00:00:00","DiscWriter_ProgressTimeChanged"}, /* Progress of a CD/DVD recording operation, expressed as the amount of time remaining until completion. */
               {"DiscWriter_ProgressPercentageChanged",36,MINT,0,"Undefined",	"00:00:00","DiscWriter_ProgressPercentageChanged"},	/* Update on the progress of a CD/DVD recording operation, expressed as the percentage completed. */
               {"DiscWriter_SelectedFormat",           25,MDIS,0,"Undefined",	"00:00:00","DiscWriter_SelectedFormat"},/* Selected recording format for a CD/DVD recording operation. */
               {"DiscWriter_Start",                    16,MBOO,0,"False",		"00:00:00","DiscWriter_Start"},	/* CD/DVD recording operation has begun. */
               {"DiscWriter_Stop",                     15,MBOO,0,"False",		"00:00:00","DiscWriter_Stop"},/* CD/DVD recording operation has concluded. */
               {"DVD",                                  3,MBOO,0,"False",		"00:00:00","DVD"	     },	/* DVD playback has started. */
               {"Ejecting",                             8,MBOO,0,"False",		"00:00:00","Ejecting"	 },	/* Disc was ejected from the CD/DVD drive. This status is sent only if Windows Media Center was playing the disc. */
               {"EndSession",                          10,MINT,0,"Undefined",	"00:00:00","EndSession"	 },	/* End of session */
               {"Error",                                5,MBOO,0,"False"		"00:00:00","Error"       },	/* Error occurred. */
               {"FF1",                                  3,MBOO,0,"False",		"00:00:00","Fast Forward"},	/* Fast forwarding at low speed. */
               {"FF2",                                  3,MBOO,0,"False",		"00:00:00","Faster Forward"},	/* Fast forwarding at medium speed. */
               {"FF3",                                  3,MBOO,0,"False",		"00:00:00","Fastest Forward"},/* Fast forwarding at high speed. */
               {"FS_DVD",                               6,MBOO,0,"False",		"00:00:00","DVD Playing"},	/* Navigating to Play DVD, or the DVD inset was selected. */
               {"FS_Extensibility",                    16,MBOO,0,"False",       "00:00:00","Extensibility"},/* Navigating to a hosted HTML application. */
               {"FS_Guide",                             8,MBOO,0,"False",       "00:00:00","Guide"       }, /* Navigating to Guide. */
               {"FS_Home",                              7,MBOO,0,"False",       "00:00:00","Media Center"},/* Navigating to Windows Media Center Start page. */
               {"FS_Music",                             8,MBOO,0,"False",       "00:00:00","Music"       },/* Navigating to My Music, or the music inset was selected. */
               {"FS_Photos",                            9,MBOO,0,"False",       "00:00:00","Photo"       },/* Navigating to My Pictures. */
               {"FS_Radio",                             8,MBOO,0,"False",       "00:00:00","Radio"       },/* Navigating to Radio. */
               {"FS_RecordedShows",                    16,MBOO,0,"False",       "00:00:00","Recorded Show"},/* Navigating to Recorded Shows or scheduled recording pages, or the recorded TV inset was selected. */
               {"FS_TV",                                5,MBOO,0,"False",       "00:00:00","TV"          }, /* Navigating to My TV, or the TV inset was selected. */
               {"FS_Unknown",                          10,MBOO,0,"False",       "00:00:00","Media_Center"}, /* Unknown Windows Media Center status. */
               {"FS_Videos",                            9,MBOO,0,"False",       "00:00:00","Video"       }, /* Navigating to My Videos, or the video inset was selected. */
               {"GuideLoaded",                         11,MBOO,0,"False",       "00:00:00","GuideLoaded"}, /* Downloaded a new guide. */
               {"KeyPress",                             8,MINT,0,"Undefined",   "00:00:00","KeyPress"    }, /* Key Pressed (Volume up down?) */
               {"MediaName",                            9,MSTR,0,"Undefined",   "00:00:00","MediaName"   }, /* Name of the current media. This status is sent when the media starts. */
               {"MediaTime",                            9,MTIM,0,"Undefined",   "00:00:00","MediaTime"   }, /* Length of the current media. */
               {"MediaTypes",                          10,MUNK,0,"Undefined",   "00:00:00","MediaTypes"  }, /* Placeholder for enumerated values beginning at 0x2000; not a notification. */
               {"MSASPrivateTags",                     15,MUNK,0,"Undefined",   "00:00:00","MSASPrivateTags"}, /* Placeholder for enumerated values beginning at 0xF000; not a notification. */
               {"Mute",                                 4,MBOO,0,"False",       "00:00:00","Mute"        }, /*Muting was turned on or off. */
               {"Next",                                 4,MBOO,0,"False",       "00:00:00","Next"        }, /* Skipping forward to next track or chapter. */
               {"NextFrame",                            9,MBOO,0,"False",       "00:00:00","Next Frame"  }, /* Skipping forward to next frame while paused. */
               {"ParentalAdvisoryRating",              22,MSTR,0,"Undefined",   "00:00:00","ParentalAdvisoryRating"}, /* Parental advisory rating of current show. */
               {"Pause",                                5,MBOO,0,"False",       "00:00:00","Pause"       }, /* Pausing the media. */
               {"PhoneCall",                            9,MBOO,0,"False",       "00:00:00","Phone Call"  }, /* Incoming phone call. */
               {"Photos",                               6,MBOO,0,"False",       "00:00:00","Photos"      }, /* Picture was selected. */
               {"Play",                                 4,MBOO,0,"False",       "00:00:00","Play"        }, /* Starting to play the current media. */
               {"Prev",                                 4,MBOO,0,"False",       "00:00:00","Previous"    },/* Skipping backward to the previous track or chapter. */
               {"PrevFrame",                            9,MBOO,0,"False",       "00:00:00","Previous Frame"},/* Skipping backward to the previous frame while paused. */
               {"PVR",                                  3,MBOO,0,"False",       "00:00:00","PVR"         }, /* Starting a recorded show. */
               {"Radio",                                5,MBOO,0,"False",       "00:00:00","Radio"       }, /* Radio or radio frequency scanning has started. */
               {"RadioFrequency",                      14,MSTR,0,"Undefined",   "00:00:00","RadioFrequency"}, /* Current radio frequency. This status is sent when a new radio frequency is selected. */
               {"Recording",                            9,MBOO,0,"False",       "00:00:00","Recording"   }, /* Recording has started. */
               {"RequestForTuner",                     15,MUNK,0,"Undefined",   "00:00:00","RequestForTuner"}, /* An application has requested the use of a TV tuner. */
               {"RepeatSet",                            9,MBOO,0,"False",       "00:00:00","RepeatSet"   }, /* Repeat was enabled or disabled. */
               {"Rewind1",                              7,MBOO,0,"False",       "00:00:00","Rewind"      }, /* Rewinding at low speed. */
               {"Rewind2",                              7,MBOO,0,"False",       "00:00:00","Fast Rewind" }, /* Rewinding at medium speed. */
               {"Rewind3",                              7,MBOO,0,"False",       "00:00:00","Fastest Rewind"},/* Rewinding at high speed. */
               {"Shuffle",                              7,MBOO,0,"False",       "00:00:00","Shuffle"     }, /* Shuffle was enabled or disabled. */
               {"SlowMotion1",                         11,MBOO,0,"False",       "00:00:00","Slow Motion" }, /* Playing at low slow-motion speed. */
               {"SlowMotion2",                         11,MBOO,0,"False",       "00:00:00","Slower Motion"},/* Playing at medium slow-motion speed. */
               {"SlowMotion3",                         11,MBOO,0,"False",       "00:00:00","Slowest Motion"},/* Playing at high slow-motion speed. */
               {"StartSession",                        12,MINT,0,"Undefined",   "00:00:00","StartSession"}, /* Start of session */
               {"Stop",                                 4,MBOO,1,"True",        "00:00:00","Stop"        }, /* Current media was stopped. This status is sent once when stop is selected, and once when the media has stopped.*/
               {"StreamingContentAudio",               21,MBOO,0,"False",       "00:00:00","Audio"       }, /* Audio content being played back from the hard disk. */
               {"StreamingContentVideo",               21,MBOO,0,"False",       "00:00:00","Video"       }, /* Video content being played back from the hard disk. */
               {"TitleNumber",                         11,MINT,0,"Undefined",   "00:00:00","TitleNumber" }, /* Number of the current title. */
               {"TotalTracks",                         11,MINT,0,"Undefined",   "00:00:00","TotalTracks" }, /* Total number of tracks on the current media. */
               {"TrackDuration",                       13,MTIM,0,"Undefined",   "00:00:00","TrackDuration"}, /* Duration, in seconds, of the current track. */
               {"TrackName",                            9,MSTR,0,"Undefined",   "00:00:00","TrackName"   }, /* Name of the current track. */
               {"TrackNumber",                         11,MINT,0,"Undefined",   "00:00:00","TrackNumber" }, /* CD track number, DVD chapter number, or TV channel number. */
               {"TrackTime",                            9,MTIM,0,"Undefined",   "00:00:00","TrackTime"   }, /* Elapsed time, in seconds, within the current track. This status is incremented and sent every second. */
               {"TransitionTime",                      14,MTIM,0,"Undefined",   "00:00:00","TransitionTime"}, /* Duration, in seconds, of transitions between slides in a slide show. */
               {"TVTuner",                              7,MBOO,0,"False",       "00:00:00","TVTuner"     }, /* TV has started. */
               {"Unknown",                              7,MBOO,0,"False",       "00:00:00","Unknown"     }, /* Unknown property. */
               {"Visualization",                       13,MBOO,0,"False",       "00:00:00","Visualization"}, /* Visualization has started or stopped. */
               {"Volume",                               6,MINT,0,"Undefined",   "00:00:00","Volume"      }, /* Current volume level. This status is sent when the volume changes. */
               {"TrackTimeLeft",                       13,MTIM,0,"Undefined",   "00:00:00","TrackTimeLeft"}, /* Remaining Track time. */
               {"ChannelName",                         11,MSTR,0,"Undefined",   "00:00:00","ChannelName" }, /* TV Channel Name */
               {"SessionType",                         11,MSTR,0,"Undefined",   "00:00:00","SessionType" }, /* Current type of session */
               {"NextSessionType",                     15,MSTR,0,"Undefined",   "00:00:00","NextSessionType"}, /* Current type of next session */
               {"RecordingStatus",                     15,MINT,0,"Undefined",   "00:00:00","RecordingStatus"}, /* Status of Recording */
               {"RecordingSession",                    16,MINT,0,"Undefined",   "00:00:00","RecordingSession"}, /* Current type of next session */
               {"RecordingMediaName",                  18,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName"}, /* Name of media being recorded */
               {"RecordingTrackNumber",                20,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber"}, /* Channel Number being recorded */
               {"RecordingChannelName",                20,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName"}, /* Channel Name being recorded */
               {"PreviousStatusFlag",                  18,MINT,0,"Undefined",   "00:00:00","PreviousStatusFlag"}, /* Previous Session Value */
               {"UseBars",                              7,MINT,0,"False",       "00:00:00","UseBars"     }, /* Use bars for time displays in F1/F2 */
               {"IPAddress",                            9,MSTR,0,"127.0.0.1",   "00:00:00","IPAddress"   }, /* IP Address for TCPIPController */
               {"IPPort",                               6,MINT,40400,"40400",   "00:00:00","IPPort"      }, /* IP Port for TCPIPController */
               {"IPRemote",                             8,MINT,0,"0",           "00:00:00","IPRemote"    }, /* IP is local */
               {"SessionFlag",                         11,MINT,0,"0",           "00:00:00","SessionFlag" }, /* session number if session type expected */
               {"SessionStatus",                       13,MSTR,0,"0",           "00:00:00","SessionStatus"},/* Current session status string */
               {"SessionValue",                        12,MINT,0,"0",           "00:00:00","SessionValue"}, /* Current session status value (CD etc.} */
               {"RecordingStatus1",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus1"},/* Status of Recording */          
               {"RecordingSession1",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession1"},/* Current type of next session */
               {"RecordingMediaName1",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName1"},/* Name of media being recorded */
               {"RecordingTrackNumber1",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber1"}, /* Channel Number being recorded */
               {"RecordingChannelName1",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName1"},/* Channel Name being recorded */
               {"RecordingStatus2",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus2"},/* Status of Recording */          
               {"RecordingSession2",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession2"},/* Current type of next session */
               {"RecordingMediaName2",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName2"}/* Name of media being recorded */,
               {"RecordingTrackNumber2",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber2"},/* Channel Number being recorded */
               {"RecordingChannelName2",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName2"},/* Channel Name being recorded */  
               {"RecordingStatus3",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus3"},/* Status of Recording */          
               {"RecordingSession3",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession3"},/* Current type of next session */
               {"RecordingMediaName3",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName3"}, /* Name of media being recorded */
               {"RecordingTrackNumber3",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber3"},/* Channel Number being recorded */
               {"RecordingChannelName3",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName3"},/* Channel Name being recorded */  
               {"RecordingStatus4",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus4"},/* Status of Recording */          
               {"RecordingSession4",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession4"},/* Current type of next session */
               {"RecordingMediaName4",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName4"},/* Name of media being recorded */
               {"RecordingTrackNumber4",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber4"},/* Channel Number being recorded */
               {"RecordingChannelName4",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName4"},/* Channel Name being recorded */  
               {"RecordingStatus5",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus5"},/* Status of Recording */          
               {"RecordingSession5",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession5"},/* Current type of next session */
               {"RecordingMediaName5",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName5"},/* Name of media being recorded */
               {"RecordingTrackNumber5",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber5"},/* Channel Number being recorded */
               {"RecordingChannelName5",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName5"},/* Channel Name being recorded */  
               {"RecordingStatus6",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus6"},/* Status of Recording */          
               {"RecordingSession6",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession6"},/* Current type of next session */
               {"RecordingMediaName6",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName6"},/* Name of media being recorded */
               {"RecordingTrackNumber6",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber6"},/* Channel Number being recorded */
               {"RecordingChannelName6",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName6"},/* Channel Name being recorded */  
               {"RecordingStatus7",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus7"},/* Status of Recording */          
               {"RecordingSession7",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession7"},/* Current type of next session */
               {"RecordingMediaName7",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName7"},/* Name of media being recorded */
               {"RecordingTrackNumber7",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber7"},/* Channel Number being recorded */
               {"RecordingChannelName7",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName7"},/* Channel Name being recorded */  
               {"RecordingStatus8",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus8"},/* Status of Recording */          
               {"RecordingSession8",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession8"},/* Current type of next session */
               {"RecordingMediaName8",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName8"},/* Name of media being recorded */
               {"RecordingTrackNumber8",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber8"},/* Channel Number being recorded */
               {"RecordingChannelName8",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName8"},/* Channel Name being recorded */  
               {"RecordingStatus9",                    16,MINT,0,"Undefined",   "00:00:00","RecordingStatus9"},/* Status of Recording */          
               {"RecordingSession9",                   17,MINT,0,"Undefined",   "00:00:00","RecordingSession9"},/* Current type of next session */
               {"RecordingMediaName9",                 19,MSTR,0,"Undefined",   "00:00:00","RecordingMediaName9"},/* Name of media being recorded */
               {"RecordingTrackNumber9",               21,MINT,0,"Undefined",   "00:00:00","RecordingTrackNumber9"},/* Channel Number being recorded */
               {"RecordingChannelName9",               21,MSTR,0,"Undefined",   "00:00:00","RecordingChannelName9"},/* Channel Name being recorded */  
               {"RecordingDepth",                      14,MINT,0,"Undefined",   "00:00:00","RecordingDepth"},/* nr of simultaneous recordings */
               {"Debug",                                5,MINT,0,"Undefined",   "00:00:00","Debug"       }, /* Debug flag */                   
               {"Initialising",                        12,MINT,0,"Undefined",   "00:00:00","Initialising"},/* True during initial message receipt */
               {"IgnoreSpuriousRecording",             23,MINT,0,"Undefined",   "00:00:00","IgnoreSpuriousRecording"},/* Ignore Spurious Recording=True at startup */
               {"NewLogFile",                          10,MINT,0,"Undefined",   "00:00:00","New Log File"},/* Do we want a new log file each time? */
               {"StatusCount",                         11,MINT,2,"Undefined",   "00:00:00","StatusCount" }, /* How long to display Play/Stop/Pause/FF1/FF2/Ff3/Rw1/Rw2/Rw3 */
               {"StatusCounter",                       13,MINT,0,"Undefined",   "00:00:00","StatusCounter"},/* Current counter value */        
               {"VolumeCharacter",                     15,MINT,0,"Undefined",   "00:00:00","VolumeCharacter"},/* Volume bar character */         
               {"DisplayMode",                         11,MSTR,TAG_Stop,"Stop", "00:00:00","Display Mode"},/* Current counter tag value (incl next etc.) */
               {"ModeChar",                             8,MINT,1,"Stop",        "00:00:00","ModeChar"    },/* Custom Character to use for Mode */
               {"ModeVisible",                         11,MINT,1,"Stop",        "00:00:00","ModeVisible" },/* Whether Custom Character to be shown for Mode */
               {"Mode",                                 4,MSTR,TAG_Stop,"Stop", "00:00:00","Mode"        },/* Current counter tag value */
               {"True",                                 4,MSTR,1,"True",        "00:00:00","True"        },/* Display string for True */
               {"False",                                5,MSTR,0,"False",       "00:00:00","False"       },/* Display string for False */
               {"MediaCentre",                         11,MSTR,0,"Undefined",   "00:00:00","Media Center"},/* Display string for Media Center */
               {"Record",                               6,MSTR,0,"Undefined",   "00:00:00","Record"      },/* Display string for Record */
               {"Windows7HTPC",                        12,MSTR,0,"Undefined",   "00:00:00","Windows 7 HTPC"},/* Display string for Windows 7 HTPC */
               {"BurningDisc",                         11,MSTR,0,"Undefined",   "00:00:00","Burning Disc"},/* Display string for Burning Disc */
               {"Menu",                                 4,MSTR,0,"Undefined",   "00:00:00","Menu"        },/* Display string for Burning Disc */
               {"CCVolume",                             8,MSTR,0,"Undefined",   "00:00:00","CCVolume"    },/* String for Volume Custom Chars */
               {"CCMuteOFF",                            9,MSTR,0,"Undefined",   "00:00:00","CCCMuteOff"  },/* These must be defined highes first so search works */
               {"CCPhoneCall",                         11,MSTR,0,"Undefined",   "00:00:00","CCPhoneCall" },/* String for Custom Character */
               {"CCMute",                               6,MSTR,0,"Undefined",   "00:00:00","CCCMute"     },/* These must be defined highes first so search works */
               {"CCSlowMotion3",                       13,MSTR,0,"Undefined",   "00:00:00","CCSlowMotion3"},/* String for Custom Character */
               {"CCSlowMotion2",                       13,MSTR,0,"Undefined",   "00:00:00","CCSlowMotion2"},/* String for Custom Character */
               {"CCSlowMotion1",                       13,MSTR,0,"Undefined",   "00:00:00","CCSlowMotion1"},/* String for Custom Character */
               {"CCPrevFrame",                         11,MSTR,0,"Undefined",   "00:00:00","CCPrevFrame" },/* String for Custom Character */
               {"CCNextFrame",                         11,MSTR,0,"Undefined",   "00:00:00","CCNextFrame" },/* String for Custom Character */
               {"CCRewind3",                            9,MSTR,0,"Undefined",   "00:00:00","CCRewind3"   },/* String for Custom Character */
               {"CCRewind2",                            9,MSTR,0,"Undefined",   "00:00:00","CCRewind2"   },/* String for Custom Character */
               {"CCRewind1",                            9,MSTR,0,"Undefined",   "00:00:00","CCRewind1"   },/* String for Custom Character */
               {"CCFF3",                                5,MSTR,0,"Undefined",   "00:00:00","CCFF3"       },/* String for Custom Character */
               {"CCFF2",                                5,MSTR,0,"Undefined",   "00:00:00","CCFF2"       },/* String for Custom Character */
               {"CCFF1",                                5,MSTR,0,"Undefined",   "00:00:00","CCFF1"       },/* String for Custom Character */
               {"CCRecording",                         11,MSTR,0,"Undefined",   "00:00:00","CCRecording" },/* String for Custom Character */
               {"CCPrev",                               6,MSTR,0,"Undefined",   "00:00:00","CCPrev"      },/* String for Custom Character */
               {"CCNext",                               6,MSTR,0,"Undefined",   "00:00:00","CCNext"      },/* String for Custom Character */
               {"CCPause",                              7,MSTR,0,"Undefined",   "00:00:00","CCPause"     },/* String for Custom Character */
               {"CCStop",                               6,MSTR,0,"Undefined",   "00:00:00","CCStop"      },/* String for Custom Character */
               {"CCPlay",                               6,MSTR,0,"Undefined",   "00:00:00","CCPlay"      },/* String for Custom Character */
               {"InitCalled",                          10,MSTR,0,"Undefined",   "00:00:00","InitCalled"  },/* When Init was last called */
               {"Icon",                                 4,MSTR,0,"$CustomChar(1,31,31,31,31,31,31,31,0)$Chr(176)","00:00:00","Icon"},/* Icon String */
               {"NavStatus",                            9,MSTR,0," ",           "00:00:00","Unknown"     },/* amalgamation of FS_ tags */
               {"ChannelNotFound",                     15,MSTR,0,"Channel %d Not Found","00:00:00","Channel Not Found" },/* Channel Not Found Message*/
               {"RadioChannel",                        12,MSTR,0,"Undefined",   "00:00:00","RadioChannel"}, /* Radio Channel Name */
               {"RadioChannelTag",                     15,MSTR,0,"MediaName",   "00:00:00","RadioChannelTag" }, /* What tag to use for Radio Channel Name */
               {"UseVolIcon",                          10,MBOO,0,"False",       "00:00:00","UseVolIcon"  },/* Override Volume with Icon if set */
               {"DateFormat",                          10,MSTR,0,"%H:%M %d/%m/%y","00:00:00","DateFormat" }, /* How to display date/time */
               {"ProcessInactive",                     15,MSTR,0," ",           "00:00:00","ProcessInactive" }, /* What to return from F20 if process Inactive */
               {"EOF",3,MSTR,0,"EOF","00:00:00","EOF"}  /* Not Used! */
         
};


//================================================================================================================================
// Functions to get tag values 
// getst - get string value
// geti - get int value
// getb - get bool value as string (True or False)
// getbi - get bool value as int (0=False,non-zero=True)
// gett - get Time value as a string 
// getlength - get length of tag name
// gettag - get tag name as a string
// gettype - get default type of tag (String, MINT etc.)
// getdisplay - get display string for this tag
//================================================================================================================================
extern char * __stdcall getst(int ptr)           { return mtags[ptr].cstate; }
extern int    __stdcall geti(int ptr)            { return mtags[ptr].istate; }
extern char * __stdcall getb(int ptr)            { return mtags[ptr].cstate; }
extern int    __stdcall getbi(int ptr)           { return mtags[ptr].istate; }
extern char * __stdcall gett(int ptr)            { return mtags[ptr].tstate; }
extern int    __stdcall getlength(int ptr)       { return mtags[ptr].tag_length; }
extern char * __stdcall gettag(int ptr)          { return mtags[ptr].tag; }
extern int    __stdcall gettype(int ptr)         { return mtags[ptr].data_type; }
extern char * __stdcall getdisplay(int ptr)      { return mtags[ptr].display; }
extern double __stdcall getdb(int ptr)           { return mtags[ptr].td; }


//================================================================================================================================
// Functions to store tag values 
// putst - store string value
// puti - store int value
// putb - store bool value as string (True or False)
// putbi - store bool value as int (0=False,non-zero=True) and string
// putt - store Time value as a string 
// puttime - Store time both as MINT seconds and as a time string
//================================================================================================================================
extern void   __stdcall putst(int ptr, char *val) 
{ if (strlen(val)>MAX_CSTATE) { strncpy(mtags[ptr].cstate, val, MAX_CSTATE); mtags[ptr].cstate[MAX_CSTATE]=0; }
  else { strcpy(mtags[ptr].cstate, val); }
}
extern void   __stdcall puti(int ptr, int val)   { mtags[ptr].istate=val; }
extern void   __stdcall putb(int ptr, char *val) { strcpy(mtags[ptr].cstate, val); }
extern void   __stdcall putbi(int ptr, int val)   
{  mtags[ptr].istate=val;
   if (val==0) {strcpy(mtags[ptr].cstate,getdisplay(TAG_False));} else {strcpy(mtags[ptr].cstate,getdisplay(TAG_True));}
}
extern void   __stdcall putt(int ptr, char *val) { strcpy(mtags[ptr].tstate, val); }
extern void   __stdcall puttime(int ptr, int val) 
{  int tr_hours,tr_mins,tr_secs;
   puti(ptr,val); tr_hours=val/3600; tr_mins=(val-(tr_hours*3600))/60; tr_secs=val%60;
   sprintf(mtags[ptr].tstate,"%d:%02d:%02d",tr_hours,tr_mins,tr_secs);
}
extern void   __stdcall putdb(int ptr, double val) { mtags[ptr].td=val; }

//================================================================================================================================
// routine to evaluate two tags as times and return as a string
//================================================================================================================================
extern void  __stdcall gettimes(char * buf, int tag1, int tag2)
{  int tr,tr_hours,tr_mins,tr_secs,tl,tl_hours,tl_mins,tl_secs;

   tr=geti(tag1); tr_hours=tr/3600; tr_mins=(tr-(tr_hours*3600))/60; tr_secs=tr%60;
   tl=geti(tag2); tl_hours=tl/3600; tl_mins=(tl-(tl_hours*3600))/60; tl_secs=tl%60;
   sprintf(buf,"%d:%02d:%02d/%d:%02d:%02d",tr_hours,tr_mins,tr_secs,tl_hours,tl_mins,tl_secs);
}

//================================================================================================================================
// function to store a tag value from an input line "param=value"
// 
//================================================================================================================================
extern int __stdcall puttag(char *line, char *wass, int *wasi)
{  int tag,found;

   Tlog("puttag processing line",line);
   found=0;
   for (tag=0; tag<NUM_MTAGS; tag++)
       { // check it's tag= and it's this entry in the tag table
         if ((!strncmp(gettag(tag),line,getlength(tag))) && (line[getlength(tag)]=='='))
            { strcpy(wass,getst(tag));               // Save the previous values
              *wasi=geti(tag);                       // Store previous integer value
              
              putst(tag,&line[getlength(tag)+1]); // store the string value in this tag
              
              if      (gettype(tag)==MINT) { puti(tag,atoi(&line[getlength(tag)+1])); }
              else if (gettype(tag)==MBOO) { putbi(tag,0); if (line[getlength(tag)+1]=='T') putbi(tag,1); }
              else if (gettype(tag)==MTIM) { puttime(tag,atoi(&line[getlength(tag)+1])); }
              else if (gettype(tag)!=MSTR) { Tlog("*** puttag - Tag data type not found ***",line); }
//              Tlog("puttag - tag found",gettag(tag));
              found=1;
              break;
            }
       }
   if (found==0) Tlog("puttag *** Tag not found ***",line); 
//   printf("Tag=%d,NUM_MTAGS=%d,%s\n",tag,NUM_MTAGS,line);
   return tag;
} 

//================================================================================================================================
// function to sore a tag display name from an input line "param=value"
// 
//================================================================================================================================
extern void   __stdcall putdisplay(char *line)
{  int tag,found,len;
   char str[256];

   Tlog("putdisplay processing line",line);
   found=0;
   strcpy(str,line);
   for (tag=0; tag<NUM_MTAGS; tag++)
       { // check it's tag= and it's this entry in the tag table
         len=getlength(tag);
         if ((!strncmp(gettag(tag),str,len)) && (str[len]=='='))
            { if (strlen(str)>(MAX_CSTATE+len+1)) { str[40+len+1]=0; }
              strcpy(mtags[tag].display,&str[len+1]);
              Tlog("putdisplay - tag found",getdisplay(tag));
              found=1;
              break;
            }
       }
   if (found==0) Tlog("getdisplay *** Tag not found ***",line);
}


//================================================================================================================================
// routine to clear out the tag structure values
//================================================================================================================================
extern void  __stdcall clear_tags(void)
{ int i;

  for (i=0; i<NUM_MTAGS; i++) { mtags[i].istate=0; }
}

//================================================================================================================================
// routine to Check out the tag structure values
//================================================================================================================================
extern void  __stdcall MCE_check_tags(void)
{ int i; char str[80];

  for (i=0; i<NUM_MTAGS; i++) { if (strlen(mtags[i].tag)!=mtags[i].tag_length) Tlog("***** Invalid tag entry at",mtags[i].tag); }
  i=sizeof(mtags); sprintf(str,"mtags table size=%d",i); Tlog("***** check_mtags",str);
  if (strncmp(gettag(TAG_Icon),"Icon",4)) Tlog("***** Icon entry wrong - reads ",gettag(TAG_Icon));
}


//================================================================================================================================
// function to copy a string and set the first newline character to 0
//================================================================================================================================
extern void __stdcall strcpytonl(char *so, char *si)
{ int i;
  for (i=0; i<strlen(si); i++) { if (si[i]=='\n') { so[i]=0; break; } else so[i]=si[i]; }
}

